package com.gitee.wsl.jvm.exception

open class JobRunrException : RuntimeException {

    val isProblematicAndDoNotRetry: Boolean

    constructor(message: String?, cause: Throwable?) : this(message, false, cause)

    @JvmOverloads
    constructor(message: String?, doNotRetry: Boolean = false) : super(message) {
        this.isProblematicAndDoNotRetry = doNotRetry
    }

    constructor(message: String?, doNotRetry: Boolean, cause: Throwable?) : super(message, cause) {
        this.isProblematicAndDoNotRetry = doNotRetry
    }

    companion object {
        const val SHOULD_NOT_HAPPEN_MESSAGE: String =
            "JobRunr encountered a problematic exception. Please create a bug report (if possible, provide the code to reproduce this and the stacktrace)"
        const val INVALID_LAMBDA_MESSAGE: String = "The lambda you provided is not valid."

        fun shouldNotHappenException(message: String?): JobRunrException {
            return JobRunrException(SHOULD_NOT_HAPPEN_MESSAGE, IllegalStateException(message))
        }

        fun invalidLambdaException(exception: Exception?): JobRunrException {
            return JobRunrException(INVALID_LAMBDA_MESSAGE, exception)
        }

        fun shouldNotHappenException(cause: Throwable): JobRunrException {
            if (cause is JobRunrException) return cause
            if (cause.cause is JobRunrException) return cause.cause as JobRunrException
            return JobRunrException(SHOULD_NOT_HAPPEN_MESSAGE, cause)
        }

        fun configurationException(message: String?): JobRunrException {
            return JobRunrException(message)
        }

        fun problematicConfigurationException(message: String?): JobRunrException {
            return JobRunrException(message, true)
        }

        fun problematicException(message: String?, cause: Throwable?): JobRunrException {
            return JobRunrException(message, true, cause)
        }

        fun configurationException(message: String?, cause: Throwable): JobRunrException {
            if (cause is JobRunrException) return cause
            if (cause.cause is JobRunrException) return cause.cause as JobRunrException
            return JobRunrException(message, cause)
        }
    }
}
